typedef struct {
u32 domid;
- unsigned int cpu;
+ unsigned int flags;
+ unsigned int processors;
unsigned int vcpus;
+ u16 n_vcpus;
unsigned int dying:1, crashed:1, shutdown:1,
paused:1, blocked:1, running:1;
unsigned int shutdown_reason; /* only meaningful if shutdown==1 */
* domain
* @return 0 on success, -1 on failure
*/
-int xc_domain_getfullinfo(int xc_handle,
- u32 domid,
- u32 vcpu,
- xc_domaininfo_t *info,
- vcpu_guest_context_t *ctxt);
+int xc_domain_get_vcpu_context(int xc_handle,
+ u32 domid,
+ u32 vcpu,
+ vcpu_guest_context_t *ctxt);
+
int xc_domain_setcpuweight(int xc_handle,
u32 domid,
float weight);
/* number of pages to write at a time */
#define DUMP_INCREMENT 4 * 1024
#define round_pgup(_p) (((_p)+(PAGE_SIZE-1))&PAGE_MASK)
+
static int
copy_from_domain_page(int xc_handle,
u32 domid,
u32 domid,
const char *corename)
{
- vcpu_guest_context_t st_ctxt, *ctxt = &st_ctxt;
unsigned long nr_pages;
unsigned long *page_array;
- xc_domaininfo_t st_info, *info = &st_info;
+ xc_dominfo_t info;
int i, dump_fd;
char *dump_mem, *dump_mem_start = NULL;
struct xc_core_header header;
+ vcpu_guest_context_t ctxt[MAX_VIRT_CPUS];
+
if ((dump_fd = open(corename, O_CREAT|O_RDWR, S_IWUSR|S_IRUSR)) < 0) {
PERROR("Could not open corefile %s: %s", corename, strerror(errno));
goto error_out;
}
- if (xc_domain_getfullinfo(xc_handle, domid, 0/* XXX hardcode */, info, ctxt)) {
- PERROR("Could not get full info for domain");
+ if (xc_domain_getinfo(xc_handle, domid, 1, &info)) {
+ PERROR("Could not get info for domain");
goto error_out;
}
+
+ for (i = 0; i < info.n_vcpus; i++) {
+ if (xc_domain_get_vcpu_context(xc_handle, domid, i, &ctxt[i])) {
+ PERROR("Could not get all vcpu contexts for domain");
+ goto error_out;
+ }
+ }
+
+ nr_pages = info.nr_pages;
- nr_pages = info->tot_pages;
header.xch_magic = 0xF00FEBED;
- header.xch_nr_vcpus = 1; /* no interface to query at the moment */
+ header.xch_nr_vcpus = info.n_vcpus;
header.xch_nr_pages = nr_pages;
header.xch_ctxt_offset = sizeof(struct xc_core_header);
header.xch_index_offset = sizeof(struct xc_core_header) +
sizeof(vcpu_guest_context_t) + nr_pages * sizeof(unsigned long));
write(dump_fd, &header, sizeof(struct xc_core_header));
- write(dump_fd, ctxt, sizeof(st_ctxt));
+ write(dump_fd, &ctxt, sizeof(ctxt[0]) * info.n_vcpus);
if ((page_array = malloc(nr_pages * sizeof(unsigned long))) == NULL) {
printf("Could not allocate memory\n");
{
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t)next_domid;
- op.u.getdomaininfo.exec_domain = 0; // FIX ME?!?
- op.u.getdomaininfo.ctxt = NULL; /* no exec context info, thanks. */
if ( (rc = do_dom0_op(xc_handle, &op)) < 0 )
break;
- info->domid = (u16)op.u.getdomaininfo.domain;
-
- info->cpu =
- (op.u.getdomaininfo.flags>>DOMFLAGS_CPUSHIFT) & DOMFLAGS_CPUMASK;
+ info->domid = (u16)op.u.getdomaininfo.domain;
+ info->processors = op.u.getdomaininfo.processors;
+ info->n_vcpus = op.u.getdomaininfo.n_active_vcpus;
+ info->flags = op.u.getdomaininfo.flags;
info->dying = !!(op.u.getdomaininfo.flags & DOMFLAGS_DYING);
info->crashed = !!(op.u.getdomaininfo.flags & DOMFLAGS_CRASHED);
memcpy(&info->cpumap, &op.u.getdomaininfo.cpumap,
sizeof(info->cpumap));
- next_domid = (u16)op.u.getdomaininfo.domain + 1;
- info++;
+ next_domid = (u16)op.u.getdomaininfo.domain + 1;
+ info++;
}
- if(!nr_doms) return rc;
+ if( !nr_doms ) return rc;
return nr_doms;
}
-int xc_domain_getfullinfo(int xc_handle,
- u32 domid,
- u32 vcpu,
- xc_domaininfo_t *info,
- vcpu_guest_context_t *ctxt)
+int xc_domain_get_vcpu_context(int xc_handle,
+ u32 domid,
+ u32 vcpu,
+ vcpu_guest_context_t *ctxt)
{
int rc, errno_saved;
dom0_op_t op;
- op.cmd = DOM0_GETDOMAININFO;
- op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.exec_domain = (u16)vcpu;
- op.u.getdomaininfo.ctxt = ctxt;
+ op.cmd = DOM0_GETVCPUCONTEXT;
+ op.u.getvcpucontext.domain = (domid_t)domid;
+ op.u.getvcpucontext.exec_domain = (u16)vcpu;
+ op.u.getvcpucontext.ctxt = ctxt;
if ( (ctxt != NULL) &&
((rc = mlock(ctxt, sizeof(*ctxt))) != 0) )
errno = errno_saved;
}
- if ( info != NULL )
- memcpy(info, &op.u.getdomaininfo, sizeof(*info));
-
- if ( ((u16)op.u.getdomaininfo.domain != domid) && (rc > 0) )
+ if ( rc > 0 )
return -ESRCH;
else
return rc;
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = ctxt;
if ( (do_dom0_op(xc_handle, &op) < 0) ||
((u16)op.u.getdomaininfo.domain != domid) )
{
PERROR("Could not get info on domain");
goto error_out;
}
+
+ if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
+ {
+ PERROR("Could not get vcpu context");
+ goto error_out;
+ }
+
if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
(ctxt->pt_base != 0) )
{
/* Get the domain's shared-info frame. */
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t)dom;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = NULL;
if ( do_dom0_op(xc_handle, &op) < 0 )
{
xcio_error(ioctxt, "Could not get information on new domain");
int suspend_and_state(int xc_handle, XcIOContext *ioctxt,
- xc_domaininfo_t *info,
+ xc_dominfo_t *info,
vcpu_guest_context_t *ctxt)
{
int i=0;
retry:
- if ( xc_domain_getfullinfo(xc_handle, ioctxt->domain, /* FIXME */ 0,
- info, ctxt) )
+ if ( xc_domain_getinfo(xc_handle, ioctxt->domain, 1, info) )
{
xcio_error(ioctxt, "Could not get full domain info");
return -1;
}
+ if ( xc_domain_get_vcpu_context(xc_handle, ioctxt->domain, 0 /* XXX */,
+ ctxt) )
+ {
+ xcio_error(ioctxt, "Could not get vcpu context");
+ }
+
if ( (info->flags &
(DOMFLAGS_SHUTDOWN | (SHUTDOWN_suspend<<DOMFLAGS_SHUTDOWNSHIFT))) ==
(DOMFLAGS_SHUTDOWN | (SHUTDOWN_suspend<<DOMFLAGS_SHUTDOWNSHIFT)) )
int xc_linux_save(int xc_handle, XcIOContext *ioctxt)
{
- xc_domaininfo_t info;
+ xc_dominfo_t info;
int rc = 1, i, j, k, last_iter, iter = 0;
unsigned long mfn;
xcio_perror(ioctxt, "Unable to mlock ctxt");
return 1;
}
-
- if ( xc_domain_getfullinfo( xc_handle, domid, /* FIXME */ 0,
- &info, &ctxt) )
+
+ if ( xc_domain_getinfo(xc_handle, domid, 1, &info) )
{
xcio_error(ioctxt, "Could not get full domain info");
goto out;
}
+ if ( xc_domain_get_vcpu_context( xc_handle, domid, /* FIXME */ 0,
+ &ctxt) )
+ {
+ xcio_error(ioctxt, "Could not get vcpu context");
+ goto out;
+ }
shared_info_frame = info.shared_info_frame;
/* A cheesy test to see whether the domain contains valid state. */
goto out;
}
- nr_pfns = info.max_pages;
+ nr_pfns = info.nr_pages;
/* cheesy sanity check */
if ( nr_pfns > 1024*1024 ){
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t) domid;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = ctxt;
if ((do_dom0_op(xc_handle, &op) < 0) ||
((u32) op.u.getdomaininfo.domain != domid)) {
PERROR("Could not get info on domain");
goto error_out;
}
DPRINTF(("xc_get_tot_pages returns %ld pages\n", tot_pages));
+
+ if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
+ {
+ PERROR("Could not get vcpu context");
+ goto error_out;
+ }
if (!(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED)
- || (op.u.getdomaininfo.ctxt->pt_base != 0)) {
+ || (ctxt->pt_base != 0)) {
ERROR("Domain is already constructed");
goto error_out;
}
{
dom0_op_t op;
- op.cmd = DOM0_GETDOMAININFO;
- op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.exec_domain = (u16)vcpu;
- op.u.getdomaininfo.ctxt = NULL;
- if ( (do_dom0_op(xc_handle, &op) < 0) ||
- ((u16)op.u.getdomaininfo.domain != domid) )
+ op.cmd = DOM0_GETVCPUCONTEXT;
+ op.u.getvcpucontext.domain = (domid_t)domid;
+ op.u.getvcpucontext.exec_domain = (u16)vcpu;
+ op.u.getvcpucontext.ctxt = NULL;
+ if ( (do_dom0_op(xc_handle, &op) < 0) )
{
PERROR("Could not get info on domain");
return -1;
}
- return op.u.getdomaininfo.cpu_time;
+ return op.u.getvcpucontext.cpu_time;
}
dom0_op_t op;
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = NULL;
return (do_dom0_op(xc_handle, &op) < 0) ?
-1 : op.u.getdomaininfo.tot_pages;
}
#define FETCH_REGS(cpu) \
if (!regs_valid[cpu]) \
{ \
- int retval = xc_domain_getfullinfo(xc_handle, domid, cpu, NULL, &ctxt[cpu]); \
+ int retval = xc_domain_get_vcpu_context(xc_handle, domid, cpu, &ctxt[cpu]); \
if (retval) \
goto error_out; \
cr3[cpu] = ctxt[cpu].pt_base; /* physical address */ \
{
dom0_op_t op;
int retval;
- vcpu_guest_context_t ctxt;
struct timespec ts;
ts.tv_sec = 0;
ts.tv_nsec = 10*1000*1000;
}
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = domain;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = &ctxt;
retry:
retval = do_dom0_op(xc_handle, &op);
- if (retval) {
+ if (retval || op.u.getdomaininfo.domain != domain) {
printf("getdomaininfo failed\n");
goto done;
}
case PTRACE_ATTACH:
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = domid;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = NULL;
retval = do_dom0_op(xc_handle, &op);
- if (retval) {
+ if (retval || op.u.getdomaininfo.domain != domid) {
perror("dom0 op failed");
goto error_out;
}
op.cmd = DOM0_GETDOMAININFO;
op.u.getdomaininfo.domain = (domid_t)domid;
- op.u.getdomaininfo.exec_domain = 0;
- op.u.getdomaininfo.ctxt = ctxt;
if ( (do_dom0_op(xc_handle, &op) < 0) ||
((u16)op.u.getdomaininfo.domain != domid) )
{
PERROR("Could not get info on domain");
goto error_out;
}
+
+ if ( xc_domain_get_vcpu_context(xc_handle, domid, 0, ctxt) )
+ {
+ PERROR("Could not get vcpu context");
+ goto error_out;
+ }
+
if ( !(op.u.getdomaininfo.flags & DOMFLAGS_PAUSED) ||
(ctxt->pt_base != 0) )
{
case DOM0_GETDOMAININFO:
{
- struct vcpu_guest_context *c;
- struct domain *d;
- struct exec_domain *ed;
+ struct domain *d;
+ struct exec_domain *ed;
+ u64 cpu_time = 0;
+ int vcpu_count = 0;
+ u32 processors = 0;
+ int flags = DOMFLAGS_PAUSED | DOMFLAGS_BLOCKED;
+
+#if MAX_VIRT_CPUS > 32
+#error "update processors field in GETDOMAININFO"
+#endif
read_lock(&domlist_lock);
op->u.getdomaininfo.domain = d->id;
- if ( (op->u.getdomaininfo.exec_domain >= MAX_VIRT_CPUS) ||
- !d->exec_domain[op->u.getdomaininfo.exec_domain] )
- {
- ret = -EINVAL;
- break;
- }
-
memset(&op->u.getdomaininfo.vcpu_to_cpu, -1,
sizeof(op->u.getdomaininfo.vcpu_to_cpu));
memset(&op->u.getdomaininfo.cpumap, 0,
op->u.getdomaininfo.cpumap[ed->id] = ed->cpumap;
}
- ed = d->exec_domain[op->u.getdomaininfo.exec_domain];
+ /*
+ * - domain is marked as paused or blocked only if all its vcpus
+ * are paused or blocked
+ * - domain is marked as running if any of its vcpus is running
+ */
+
+ for_each_exec_domain(d, ed)
+ {
+ if (!((flags & DOMFLAGS_PAUSED) && test_bit(EDF_CTRLPAUSE, &ed->flags)))
+ flags &= ~DOMFLAGS_PAUSED;
+ if (!((flags & DOMFLAGS_BLOCKED) && test_bit(EDF_BLOCKED, &ed->flags)))
+ flags &= ~DOMFLAGS_BLOCKED;
+ flags |= (test_bit(EDF_RUNNING, &ed->flags) ? DOMFLAGS_RUNNING : 0);
+
+ set_bit(ed->processor, &processors);
+ if ( ed->cpu_time > cpu_time )
+ cpu_time += ed->cpu_time;
+ vcpu_count++;
+ }
+ op->u.getdomaininfo.n_active_vcpus = vcpu_count;
+ op->u.getdomaininfo.cpu_time = cpu_time;
op->u.getdomaininfo.flags =
(test_bit( DF_DYING, &d->flags) ? DOMFLAGS_DYING : 0) |
(test_bit( DF_CRASHED, &d->flags) ? DOMFLAGS_CRASHED : 0) |
(test_bit( DF_SHUTDOWN, &d->flags) ? DOMFLAGS_SHUTDOWN : 0) |
- (test_bit(EDF_CTRLPAUSE, &ed->flags) ? DOMFLAGS_PAUSED : 0) |
- (test_bit(EDF_BLOCKED, &ed->flags) ? DOMFLAGS_BLOCKED : 0) |
- (test_bit(EDF_RUNNING, &ed->flags) ? DOMFLAGS_RUNNING : 0);
+ flags;
- op->u.getdomaininfo.flags |= ed->processor << DOMFLAGS_CPUSHIFT;
op->u.getdomaininfo.flags |=
d->shutdown_code << DOMFLAGS_SHUTDOWNSHIFT;
+ op->u.getdomaininfo.processors = processors;
op->u.getdomaininfo.tot_pages = d->tot_pages;
op->u.getdomaininfo.max_pages = d->max_pages;
- op->u.getdomaininfo.cpu_time = ed->cpu_time;
op->u.getdomaininfo.n_vcpu = d->shared_info->n_vcpu;
op->u.getdomaininfo.shared_info_frame =
__pa(d->shared_info) >> PAGE_SHIFT;
- if ( op->u.getdomaininfo.ctxt != NULL )
+ if ( copy_to_user(u_dom0_op, op, sizeof(*op)) )
+ ret = -EINVAL;
+
+ put_domain(d);
+ }
+ break;
+
+ case DOM0_GETVCPUCONTEXT:
+ {
+ struct vcpu_guest_context *c;
+ struct domain *d;
+ struct exec_domain *ed;
+ int active_index = 0;
+ int exec_domain_index;
+
+ exec_domain_index = op->u.getvcpucontext.exec_domain;
+ d = find_domain_by_id(op->u.getvcpucontext.domain);
+
+ if ( d == NULL )
+ {
+ ret = -ESRCH;
+ break;
+ }
+
+ if ( (exec_domain_index >= MAX_VIRT_CPUS) )
+ {
+ ret = -EINVAL;
+ break;
+ }
+
+ for_each_exec_domain(d, ed)
+ {
+ if ( exec_domain_index == active_index )
+ {
+ op->u.getvcpucontext.exec_domain = ed->id;
+ break;
+ }
+ active_index++;
+ }
+ op->u.getvcpucontext.cpu_time = ed->cpu_time;
+
+ if ( op->u.getvcpucontext.ctxt != NULL )
{
if ( (c = xmalloc(struct vcpu_guest_context)) == NULL )
{
if ( ed != current )
exec_domain_unpause(ed);
- if ( copy_to_user(op->u.getdomaininfo.ctxt, c, sizeof(*c)) )
+ if ( copy_to_user(op->u.getvcpucontext.ctxt, c, sizeof(*c)) )
ret = -EINVAL;
xfree(c);
typedef struct {
/* IN variables. */
domid_t domain; /* NB. IN/OUT variable. */
- u16 exec_domain;
+ u16 n_active_vcpus; /* # of vcpus currently active */
/* OUT variables. */
#define DOMFLAGS_DYING (1<<0) /* Domain is scheduled to die. */
#define DOMFLAGS_CRASHED (1<<1) /* Crashed domain; frozen for postmortem. */
#define DOMFLAGS_SHUTDOWNMASK 255 /* DOMFLAGS_SHUTDOWN guest-supplied code. */
#define DOMFLAGS_SHUTDOWNSHIFT 16
u32 flags;
- vcpu_guest_context_t *ctxt; /* NB. IN/OUT variable. */
+ u32 processors;
memory_t tot_pages;
memory_t max_pages;
memory_t shared_info_frame; /* MFN of shared_info struct */
u16 allow_access; /* allow or deny access to range? */
} dom0_ioport_permission_t;
+#define DOM0_GETVCPUCONTEXT 37
+typedef struct {
+ domid_t domain; /* domain to be affected */
+ u16 exec_domain; /* NB. IN: nth active cpu / OUT: actual cpu # */
+ vcpu_guest_context_t *ctxt; /* NB. IN/OUT variable. */
+ u64 cpu_time;
+} dom0_getvcpucontext_t;
+
+
typedef struct {
u32 cmd;
u32 interface_version; /* DOM0_INTERFACE_VERSION */
dom0_perfccontrol_t perfccontrol;
dom0_microcode_t microcode;
dom0_ioport_permission_t ioport_permission;
+ dom0_getvcpucontext_t getvcpucontext;
} u;
} dom0_op_t;